home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / linuxcon.000 / linuxcon / linuxconf-1.6 / translate / trstring.c < prev    next >
C/C++ Source or Header  |  1996-04-14  |  8KB  |  402 lines

  1. #include <ctype.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include "internal.h"
  5. #include "../misc/misc.h"
  6.  
  7. PUBLIC LANG_STRING::LANG_STRING (char _lang, const char *_str)
  8. {
  9.     lang = _lang;
  10.     str.setfrom (_str);
  11. }
  12.  
  13.  
  14. PUBLIC LANG_STRING *LANG_STRINGS::getitem(int no)
  15. {
  16.     return (LANG_STRING*)ARRAY::getitem(no);
  17. }
  18.  
  19.  
  20. PUBLIC TR_STRING::TR_STRING(const char *_id)
  21. {
  22.     changed = 0;
  23.     id.setfrom (_id);
  24. }
  25.  
  26. /*
  27.     Return the ID of the translation unit
  28. */
  29. PUBLIC const char *TR_STRING::getid()
  30. {
  31.     return id.get();
  32. }
  33. /*
  34.     Indicate if this translation unit has been modified (by msgscan).
  35.     This implied that the ID is still in use.
  36. */
  37. PUBLIC int TR_STRING::was_changed ()
  38. {
  39.     return changed;
  40. }
  41. PUBLIC void TR_STRING::reset_changed ()
  42. {
  43.     changed = 0;
  44.     rstmodified();
  45. }
  46.  
  47. /*
  48.     Return how many translation are available for this translation unit.
  49.     An obsolete message may have 0 translations.
  50. */
  51. PUBLIC int TR_STRING::getnblang()
  52. {
  53.     return tb.getnb();
  54. }
  55.  
  56. /*
  57.     Add a comment line to the TR_STRING definition.
  58. */
  59. PUBLIC void TR_STRING::add2comment(const char *_comment)
  60. {
  61.     comment.append (_comment);
  62. }
  63.  
  64. /*
  65.     Add a new translation for this message
  66. */
  67. PUBLIC SSTRING *TR_STRING::settranslation (char lang, const char *str)
  68. {
  69.     changed = 1;
  70.     setmodified();
  71.     LANG_STRING *ta = gettranslation (lang);
  72.     if (ta == NULL){
  73.         ta = new LANG_STRING (lang,str);
  74.         tb.add (ta);
  75.     }else{
  76.         ta->str.setfrom (str);
  77.     }
  78.     return &ta->str;
  79. }
  80.  
  81. /*
  82.     Get the message for a given language
  83.     Return NULL if not available.
  84. */
  85. PUBLIC LANG_STRING *TR_STRING::gettranslation (char lang)
  86. {
  87.     LANG_STRING *ret = NULL;
  88.     int n = tb.getnb();
  89.     for (int i=0; i<n; i++){
  90.         LANG_STRING *t = tb.getitem(i);
  91.         if (t->lang == lang){
  92.             ret = t;
  93.             break;
  94.         }
  95.     }
  96.     return ret;
  97. }
  98. /*
  99.     Remove one translation.
  100. */
  101. PUBLIC void TR_STRING::deltranslation (char lang)
  102. {
  103.     int n = tb.getnb();
  104.     for (int i=0; i<n; i++){
  105.         LANG_STRING *t = tb.getitem(i);
  106.         if (t->lang == lang){
  107.             tb.remove_del (t);
  108.             break;
  109.         }
  110.     }
  111. }
  112. /*
  113.     Get the message for a given language
  114.     Return NULL if not available.
  115. */
  116. PUBLIC const char *TR_STRING::getmsg (char lang)
  117. {
  118.     const char *ret = NULL;
  119.     LANG_STRING *t = gettranslation (lang);
  120.     if (t != NULL) ret = t->str.get();
  121.     return ret;
  122. }
  123.  
  124. PUBLIC void TR_STRING::write (FILE *fout)
  125. {
  126.     if (!comment.is_empty()){
  127.         fputs (comment.get(),fout);
  128.     }
  129.     fprintf (fout,"!%s\n",id.get());
  130.     int n = tb.getnb();
  131.     for (int i=0; i<n; i++){
  132.         LANG_STRING *t = tb.getitem(i);
  133.         fprintf (fout,"    :%c %s\n",t->lang,t->str.get());
  134.     }
  135. }                 
  136.  
  137.  
  138. /*
  139.     Record the string (file name) where the message was defined.
  140. */
  141. PUBLIC void TR_STRING::setorigin(const char *str)
  142. {
  143.     origin.setfrom (str);
  144. }
  145.  
  146. /*
  147.     Return the string (generally a file name) telling where the
  148.     message was defined.
  149. */
  150. PUBLIC const char *TR_STRING::getorigin()
  151. {
  152.     return origin.get();
  153. }
  154.  
  155. PUBLIC TR_STRINGS::TR_STRINGS()
  156. {
  157.     version = 0;
  158. }
  159.  
  160. PUBLIC TR_STRING *TR_STRINGS::getitem(int no)
  161. {
  162.     return (TR_STRING*)ARRAY::getitem(no);
  163. }
  164. /*
  165.     Find a translation unit with a given ID
  166.     Return NULL if not found.
  167. */
  168. PUBLIC TR_STRING *TR_STRINGS::getitem(const char *id)
  169. {
  170.     TR_STRING *ret = NULL;
  171.     int n = getnb();
  172.     for (int i=0; i<n; i++){
  173.         TR_STRING *t = getitem(i);
  174.         if (strcmp(t->getid(),id)==0){
  175.             ret = t;
  176.             break;
  177.         }
  178.     }
  179.     return ret;
  180. }
  181.  
  182.  
  183. /*
  184.     Read a string dictionary    
  185.     Return -1 if there was any errors
  186. */
  187. PUBLIC int TR_STRINGS::read (const char *fname)
  188. {
  189.     FILE *fin = vfopen (fname,"r");
  190.     int err = 0;
  191.     if (fin != NULL){
  192.         char buf[1000];
  193.         /* #Specification: string dictionary / format
  194.             The reference dictionary for the translation
  195.             system is an ASCII file. This file
  196.             contain one record for each string resource.
  197.             Each record spans multiple line with the
  198.             following format.
  199.  
  200.             Note that this is not the file used by
  201.             the running program. A binary file is produced
  202.             for each supported language.
  203.  
  204.             So here it is:
  205.  
  206.             #
  207.             # comments
  208.             # ...
  209.             @version 0
  210.             !id
  211.             :lang string ...
  212.                 +...
  213.             :lang string ...
  214.             #
  215.             "lang" is a single letter. "string" follows
  216.             "lang".
  217.             The string may continue over several line. A line
  218.             starting with a '+" is a continuation line. Everything
  219.             after is the string, including white spaces.
  220.  
  221.             Empty lines are ignored.
  222.         */
  223.         TR_STRING *cur = NULL;
  224.         SSTRING *curmsg = NULL;
  225.         int noline = 0;
  226.         SSTRING comment;
  227.         while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
  228.             noline++;
  229.             char *pt = str_skip (buf);
  230.             /* #Specification: dictionary file / comments
  231.                 msgscan is trying to preserve empty
  232.                 lines and comments between translation units.
  233.                 Not much inside translation units
  234.             */
  235.             if (pt[0] == '#' || pt[0] == '\0'){
  236.                 comment.append (buf);
  237.             }else{
  238.                 strip_end (buf);
  239.                 if (pt[0] == '@'){
  240.                     // Special commands
  241.                     pt = str_skip (pt+1);
  242.                     if (strncmp(pt,"version",7)==0
  243.                         && isspace(pt[7])){
  244.                         pt = str_skip(pt+7);
  245.                         version = atoi(pt);
  246.                     }else{
  247.                         fprintf (stderr,"Invalid line %d: %s\n"
  248.                             ,noline,buf);
  249.                         err++;
  250.                     }
  251.                 }else if (pt[0] == '!'){
  252.                     cur = new TR_STRING (str_skip(pt+1));
  253.                     add (cur);
  254.                     cur->add2comment(comment.get());
  255.                     comment.setfrom ("");
  256.                 }else if (pt[0] == ':'){
  257.                     curmsg = cur->settranslation (pt[1]
  258.                         ,str_skip(pt+2));
  259.                 }else if (pt[0] == '+'){
  260.                     curmsg->append (pt+1);
  261.                 }else if (buf[0] != '\0'){
  262.                     fprintf (stderr,"Invalid line %d: %s\n"
  263.                         ,noline,pt);
  264.                     err++;
  265.                 }
  266.             }
  267.         }
  268.         fclose (fin);
  269.         int n = getnb();
  270.         for (int i=0; i<n; i++){
  271.             TR_STRING *t = getitem(i);
  272.             t->reset_changed();
  273.         }
  274.         rstmodified();
  275.  
  276.     }
  277.     return err ? -1 : 0;
  278. }
  279.  
  280. /*
  281.     Write back the ASCII dictionary
  282.     Return -1 if any error.
  283. */
  284. PUBLIC int TR_STRINGS::write (const char *fname)
  285. {
  286.     int ret = -1;
  287.     FILE *fout = vfopen (fname,"w");
  288.     if (fout != NULL){
  289.         fprintf (fout,"@version %d\n",version);
  290.         int n = getnb();
  291.         for (int i=0; i<n; i++){
  292.             TR_STRING *t = getitem(i);
  293.             t->write (fout);
  294.         }
  295.         ret = fclose (fout);
  296.     }
  297.     return ret;
  298. }
  299.  
  300. /*
  301.     Write back the ASCII dictionary, modified entry first
  302.     Return -1 if any error.
  303. */
  304. PUBLIC int TR_STRINGS::write_mod (const char *fname)
  305. {
  306.     int ret = -1;
  307.     FILE *fout = vfopen (fname,"w");
  308.     if (fout != NULL){
  309.         fprintf (fout,"@version %d\n",version);
  310.         int n = getnb();
  311.         int i;
  312.         for (i=0; i<n; i++){
  313.             TR_STRING *t = getitem(i);
  314.             if (t->was_modified()) t->write (fout);
  315.         }
  316.         for (i=0; i<n; i++){
  317.             TR_STRING *t = getitem(i);
  318.             if (!t->was_modified()) t->write (fout);
  319.         }
  320.         ret = fclose (fout);
  321.     }
  322.     return ret;
  323. }
  324.  
  325. /*
  326.     Write the header file
  327. */
  328. PUBLIC int TR_STRINGS::writeh(const char *sysname, const char *fname)
  329. {
  330.     int ret = -1;
  331.     FILE *fout = vfopen (fname,"w");
  332.     if (fout != NULL){
  333.         fprintf (fout,"extern const char **_dictionary_%s;\n"
  334.             ,sysname);
  335.         fprintf (fout,"#ifndef DICTIONARY_REQUEST\n");
  336.         fprintf (fout,"\t#define DICTIONARY_REQUEST \\\n"
  337.             "\tconst char **_dictionary_%s;\\\n"
  338.             "\tTRANSLATE_SYSTEM_REQ _dictionary_req_%s(\"%s\",_dictionary_%s,%d,%d);\\\n"
  339.             "\tvoid dummy_dict_%s(){}\n"
  340.             ,sysname,sysname,sysname,sysname,getnb(),version,sysname);
  341.         fprintf (fout,"#endif\n");
  342.         fprintf (fout,"#ifndef MSG_U\n");
  343.         fprintf (fout,"\t#define MSG_U(id,m)\tid\n");
  344.         fprintf (fout,"\t#define MSG_B(id,m,n)\tid\n");
  345.         fprintf (fout,"\t#define MSG_R(id)\tid\n");
  346.         fprintf (fout,"#endif\n");
  347.         int n = getnb();
  348.         for (int i=0; i<n; i++){
  349.             TR_STRING *t = getitem(i);
  350.             fprintf (fout,"#define %s\t_dictionary_%s[%d]\n"
  351.                 ,t->getid(),sysname,i);
  352.         }
  353.         ret = fclose (fout);
  354.     }
  355.     return ret;
  356. }
  357.  
  358. /*
  359.     Record a version number only if it is higher than the current one.
  360. */
  361. PUBLIC void TR_STRINGS::setversion (int ver)
  362. {
  363.     if (ver > version) version = ver;
  364. }
  365.  
  366. /*
  367.     Return the version number of this dictionary.
  368. */
  369. PUBLIC int TR_STRINGS::getversion ()
  370. {
  371.     return version;
  372. }
  373.  
  374. /*
  375.     Remove one translation for all messages.
  376. */
  377. PUBLIC void TR_STRINGS::deltranslation (char lang)
  378. {
  379.     int n = getnb();
  380.     for (int i=0; i<n; i++){
  381.         TR_STRING *t = getitem(i);
  382.         t->deltranslation (lang);
  383.     }
  384. }
  385.  
  386. /*
  387.     Show all obsolete message.
  388. */
  389. PUBLIC void TR_STRINGS::showold (char deflang)
  390. {
  391.     int n = getnb();
  392.     for (int i=0; i<n; i++){
  393.         TR_STRING *t = getitem(i);
  394.         LANG_STRING *l = t->gettranslation (deflang);
  395.         if (l == NULL){
  396.             fprintf (stderr,"Obsolete message: %s\n",t->getid());
  397.         }
  398.     }
  399. }
  400.  
  401.  
  402.